package com.mashibing.apipassenger.service;


import com.mashibing.apipassenger.remote.ServicePassengerUserClient;
import com.mashibing.apipassenger.remote.ServiceVerificationCodeClient;
import com.mashibing.internalcommon.constant.CommonStatusEnum;
import com.mashibing.internalcommon.constant.IdentityConstants;
import com.mashibing.internalcommon.constant.TokenConstants;
import com.mashibing.internalcommon.dto.ResponseResult;
import com.mashibing.internalcommon.dto.TokenResult;
import com.mashibing.internalcommon.request.VerificationCodeDTO;
import com.mashibing.internalcommon.response.NumberCodeResponse;
import com.mashibing.internalcommon.response.TokenResponse;
import com.mashibing.internalcommon.util.JwtUtils;
import com.mashibing.internalcommon.util.RedisPrefixUtils;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

import static com.mashibing.internalcommon.constant.IdentityConstants.PASSENGER_IDENTITY;
import static com.mashibing.internalcommon.constant.TokenConstants.ACCESS_TOKEN_TYPE;
import static com.mashibing.internalcommon.constant.TokenConstants.REFRESH_TOKEN_TYPE;
import static com.mashibing.internalcommon.dto.ResponseResult.success;

@Service
public class VerificationCodeService {
    @Autowired
    private ServiceVerificationCodeClient serviceVerificationCodeClient;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ServicePassengerUserClient servicePassengerUserClient;


    /**
     * 生成验证码
     *
     * @param passengerPhone
     * @return
     */
    public ResponseResult generatorcode(String passengerPhone) {
        ResponseResult<NumberCodeResponse> numberCodeResponse = serviceVerificationCodeClient.getNumberCode(8);
        int numberCode = numberCodeResponse.getData().getNumberCode();
        System.out.println("收到的验证码" + numberCodeResponse);


        System.out.println("存入redis");
        String key = RedisPrefixUtils.generatorKeyByPhone(passengerPhone,IdentityConstants.PASSENGER_IDENTITY);
        stringRedisTemplate.opsForValue().set(key, numberCode + "", 2, TimeUnit.MINUTES);


        // 通过短信服务商，将对应的验证码发送到手机上。阿里短信服务，腾讯短信通，华信，容联
        return success("");
    }


    /**
     * 校验验证码
     *
     * @param passengerPhone   手机号
     * @param verificationCode 验证码
     * @return
     */

    public ResponseResult checkCode(String passengerPhone, String verificationCode) {
//根据redis读取验证码
        //生成key
        String key = RedisPrefixUtils.generatorKeyByPhone(passengerPhone,PASSENGER_IDENTITY);
        //根据key获取value
        String codeRedis = stringRedisTemplate.opsForValue().get(key);
        System.out.println("redis中的value" + codeRedis);
// 校验验证码
        if (StringUtils.isBlank(codeRedis)) {
            return ResponseResult.fail(CommonStatusEnum.VERIFICATION_CODE_ERROR.getCode(), CommonStatusEnum.VERIFICATION_CODE_ERROR.getValue());
        }
        if (!verificationCode.trim().equals(codeRedis.trim())) {
            return ResponseResult.fail(CommonStatusEnum.VERIFICATION_CODE_ERROR.getCode(), CommonStatusEnum.VERIFICATION_CODE_ERROR.getValue());
        }
// 判断是否存在用户，决定插入还是查询
        VerificationCodeDTO verificationCodeDTO = new VerificationCodeDTO();
        verificationCodeDTO.setPassengerPhone(passengerPhone);
        try {
            servicePassengerUserClient.loginOrRegister(verificationCodeDTO);
        } catch (RuntimeException e) {
            return ResponseResult.fail(CommonStatusEnum.CALL_USER_ADD_ERROR.getCode(),CommonStatusEnum.CALL_USER_ADD_ERROR.getValue());
        }

        //颁发令牌
        String accessToken = JwtUtils.generatorToken(passengerPhone, PASSENGER_IDENTITY,ACCESS_TOKEN_TYPE);
        String refreshToken = JwtUtils.generatorToken(passengerPhone, PASSENGER_IDENTITY,REFRESH_TOKEN_TYPE);

        stringRedisTemplate.setEnableTransactionSupport(true);
        SessionCallback<Boolean> sessionCallback=new SessionCallback<Boolean>() {
            @Override
            public Boolean execute(RedisOperations operations) throws DataAccessException {
                //事务开始
                stringRedisTemplate.multi();
                try {
                    //token存储到redis中
                    String accessTokenKey = RedisPrefixUtils.generatorTokenKey(passengerPhone, PASSENGER_IDENTITY, ACCESS_TOKEN_TYPE);
                    operations.opsForValue().set(accessTokenKey, accessToken, 30, TimeUnit.DAYS);
                    //        stringRedisTemplate.opsForValue().set(accessTokenKey, accessToken, 10, TimeUnit.SECONDS);

                    String refreshTokenKey = RedisPrefixUtils.generatorTokenKey(passengerPhone, PASSENGER_IDENTITY, REFRESH_TOKEN_TYPE);
                    operations.opsForValue().set(refreshTokenKey, refreshToken, 31, TimeUnit.DAYS);
                     //        stringRedisTemplate.opsForValue().set(refreshTokenKey, accessToken, 51, TimeUnit.SECONDS);
                    //事务提交
                    operations.exec();
                    return true;
                } catch (Exception e) {
                    //事务回滚
                    operations.discard();
                    return false;
                }
            }
        };
        Boolean execute = stringRedisTemplate.execute(sessionCallback);
        System.out.println("redis事务成功or失败："+execute);
        if (execute){
            // 响应
            TokenResponse tokenResponse = new TokenResponse();
            tokenResponse.setAccessToken(accessToken);
            tokenResponse.setRefreshToken(refreshToken);
            return ResponseResult.success(tokenResponse);
        }else {
            return ResponseResult.fail(CommonStatusEnum.CHECK_CODE_ERROR.getCode(),CommonStatusEnum.CHECK_CODE_ERROR.getValue());
        }

    }
}
